package com.swx.guard.service;

import com.swx.guard.bean.ServerConfig;
import com.swx.guard.bean.Service;
import com.swx.guard.bean.UpdateConfig;
import com.swx.guard.config.ServiceConfig;
import com.swx.guard.scheduling.UpdateServiceTask;
import com.swx.guard.util.PropertiesUtil;
import com.swx.guard.util.ServiceUtil;
import com.xj.starter.base.BaseServer;
import com.xj.starter.base.ServerType;
import com.xj.starter.util.FileMd5Utils;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.springframework.scheduling.annotation.Scheduled;

import javax.annotation.Resource;
import java.io.File;
import java.nio.charset.StandardCharsets;
import java.util.List;

import static com.swx.guard.consts.Const.UPDATE_CONFIG_FILE_NAME;

/**
 * @author Ricky
 * @date 2020/12/3
 */
@Slf4j
@org.springframework.stereotype.Service
public class SchedulingService {
    @Resource
    private ServiceConfig serviceConfig;


    @Scheduled(fixedDelay = 10000)
    public void fixedRate() {
        connectServer();
    }

    private void connectServer() {
        ServerConfig serverConfig = serviceConfig.getServerConfig();

        ServerType type = serverConfig.getType();
        String host = serverConfig.getHost();
        Integer port = serverConfig.getPort();
        String username = serverConfig.getUsername();
        String password = serverConfig.getPassword();

        try (BaseServer server = BaseServer.getServer(type, host, username, password, port)) {

            List<Service> serviceList = serviceConfig.getServiceList();
            for (Service service : serviceList) {
                checkService(server, service);
            }
        } catch (Exception e) {
            e.printStackTrace();
            log.error("服务器连接失败", e);
        }
    }

    @SneakyThrows
    private void checkService(BaseServer server, Service service) {
        String name = service.getName();
        String localPath = service.getLocalPath();
        File localPathDir = new File(localPath);
        if (!localPathDir.exists()) {
            throw new RuntimeException("服务【" + name + "】未部署或配置不正确，请检查！");
        }

        String serverPath = service.getServerPath();
        byte[] bytes = server.downloadToByteArray(serverPath, UPDATE_CONFIG_FILE_NAME);
        String serverVersionStr = new String(bytes, StandardCharsets.UTF_8);
        UpdateConfig serverUpdateConfig = PropertiesUtil.getUpdateConfig(serverVersionStr, UpdateConfig.class);

        File localVersionFile = new File(localPath, UPDATE_CONFIG_FILE_NAME);
        if (!localVersionFile.exists()) {
            // 版本文件不存在，升级
            log.info("本地版本文件不存在，升级");
            downloadFilesFromServer(server, service, serverUpdateConfig);
        } else {
            UpdateConfig localUpdateConfig = PropertiesUtil.getUpdateConfig(localVersionFile, UpdateConfig.class);
            if (!localUpdateConfig.getVersion().equals(serverUpdateConfig.getVersion())) {
                // 版本不相同，升级
                downloadFilesFromServer(server, service, serverUpdateConfig);
            } else {
                // 版本相同，判断本地是否需要升级
                String tempPath = "temp" + File.separator + name;
                File tempDir = new File(tempPath);
                if (!tempDir.exists()) {
                    tempDir.mkdirs();
                }
                File[] files = tempDir.listFiles();
                if (files == null || files.length == 0) {
                    return;
                }
                File tempVersionFile = new File(tempDir, UPDATE_CONFIG_FILE_NAME);
                UpdateConfig tempUpdateConfig = PropertiesUtil.getUpdateConfig(tempVersionFile, UpdateConfig.class);

                if (!localUpdateConfig.getVersion().equals(tempUpdateConfig.getVersion())) {
                    updateService(service, tempUpdateConfig.getUpdateTrigger());
                }
            }
        }
    }

    @SneakyThrows
    private void downloadFilesFromServer(BaseServer server, Service service, UpdateConfig updateConfig) {
        // 检查是否已下载
        String serviceFileName = service.getFileName();
        String name = service.getName();
        String tempPath = "temp" + File.separator + name;
        File nameDir = new File(tempPath);
        if (!nameDir.exists()) {
            nameDir.mkdirs();
        }
        File serviceFile = new File(tempPath, serviceFileName);
        if (serviceFile.exists()) {
            String fileMd5String = FileMd5Utils.getFileMd5String(serviceFile);
            if (fileMd5String.equalsIgnoreCase(updateConfig.getMd5())) {
                // 升级文件已下载，无需再次下载
                log.warn("升级文件已下载，无需再次下载");
                updateService(service, updateConfig.getUpdateTrigger());
                return;
            }
        }

        String fileName = updateConfig.getFileName();
        String serverPath = service.getServerPath();
        server.downloadFile(serverPath, fileName, tempPath);

        File file = new File(tempPath, fileName);
        File tempVersionFile = new File(tempPath, UPDATE_CONFIG_FILE_NAME);

        UpdateConfig tempUpdateConfig = new UpdateConfig();
        tempUpdateConfig.setMd5(updateConfig.getMd5());
        tempUpdateConfig.setUpdateTrigger(updateConfig.getUpdateTrigger());
        tempUpdateConfig.setVersion(updateConfig.getVersion());

        PropertiesUtil.saveObjToProperties(tempUpdateConfig, tempVersionFile.getPath());
        file.renameTo(serviceFile);

        updateService(service, tempUpdateConfig.getUpdateTrigger());
    }

    /**
     * 检查本地文件
     */
    @SneakyThrows
    public void updateAllServices() {
        List<Service> serviceList = serviceConfig.getServiceList();
        for (Service service : serviceList) {
            ServiceUtil.updateService(service);
        }
    }

    private void updateService(Service service, String cron) {
        boolean b = UpdateServiceTask.hasTask(service);
        if (!b) {
            UpdateServiceTask.addTask(service, cron);
        }
    }
}
